<html>
<script src="media_license.js"></script>
<script>

  function isHttps_() {
    return location.protocol === 'https:';
  }

  function setCookie() {
    const samesite_none_secure = '; SameSite=None; Secure';
    document.cookie = 'foo=bar; Max-Age=1000' + (isHttps_() ? samesite_none_secure : '');
    return true;
  }
  function setCookieAsync() {
    // Provided for Java.
    domAutomationController.send(setCookie());
  }

  function hasCookie() {
    return document.cookie.indexOf('foo=bar') != -1;
  }
  function hasCookieAsync() {
    // Provided for Java.
    domAutomationController.send(hasCookie());
  }

  function setSessionCookie() {
    const samesite_none_secure = '; SameSite=None; Secure';
    document.cookie = 'bar=session' + (isHttps_() ? samesite_none_secure : '');
    return true;
  }

  function hasSessionCookie() {
    return document.cookie == 'bar=session';
  }

  function setCookieStore() {
    return cookieStore.set({
      name: 'cookie-name', value: 'cookie-value', sameSite: 'none'
    })
    .then(() => true)
    .catch(() => false);
  }

  function hasCookieStore() {
    return cookieStore.get('cookie-name')
    .then((cookie) => cookie.value == 'cookie-value')
    .catch(() => false);
  }

  function setLocalStorage() {
    localStorage.setItem('foo', 'bar');
    return true;
  }
  function setLocalStorageAsync() {
    // Provided for Java.
    domAutomationController.send(setLocalStorage());
  }

  function hasLocalStorage() {
    try {
      return localStorage.getItem('foo') == 'bar';
    } catch (e) {
      return false;
    }
  }
  function hasLocalStorageAsync() {
    // Provided for Java.
    domAutomationController.send(hasLocalStorage());
  }

  function setSessionStorage() {
    sessionStorage.setItem('foo', 'bar');
    return true;
  }

  function hasSessionStorage() {
    try {
      return sessionStorage.getItem('foo') == 'bar';
    } catch (e) {
      return false;
    }
  }

  function setServiceWorker() {
    return navigator.serviceWorker.register('empty_worker.js')
    .then(() => navigator.serviceWorker.ready)
    .then(() => true)
    .catch(() => false);
  }
  async function setServiceWorkerAsync() {
    // Provided for Java.
    domAutomationController.send(await setServiceWorker());
  }

  function hasServiceWorker() {
    return navigator.serviceWorker.getRegistrations()
    .then((registrations) => registrations.length > 0)
    .catch(() => false);
  }
  async function hasServiceWorkerAsync() {
    // Provided for Java.
    domAutomationController.send(await hasServiceWorker());
  }

  function setCacheStorage() {
    return caches.open("cache")
    .then((cache) => cache.put("/foo", new Response("bar")))
    .then(() => true)
    .catch(() => false);
  }
  async function setCacheStorageAsync() {
    // Provided for Java.
    domAutomationController.send(await setCacheStorage());
  }

  function hasCacheStorage() {
    return caches.open("cache")
    .then((cache) => cache.keys())
    .then((keys) => keys.length > 0)
    .catch(() => false);
  }
  async function hasCacheStorageAsync() {
    // Provided for Java.
    domAutomationController.send(await hasCacheStorage());
  }

  async function openFile_(name, options, callback, error) {
    const fs = await new Promise((resolve, reject) => {
      window.webkitRequestFileSystem(TEMPORARY, 1024, resolve, reject);
    });
    return new Promise((resolve, reject) => {
      fs.root.getFile(name, options, resolve, reject);
    });
  }

  function setFileSystem() {
    return openFile_('foo.txt', { create: true, exclusive: true })
    .then(() => true)
    .catch(() => false);
  }
  async function setFileSystemAsync() {
    // Provided for Java.
    domAutomationController.send(await setFileSystem());
  }

  function hasFileSystem() {
    return openFile_('foo.txt', { create: false })
    .then(() => true)
    .catch(() => false);
  }
  async function hasFileSystemAsync() {
    // Provided for Java.
    domAutomationController.send(await hasFileSystem());
  }

  async function setFileSystemAccess() {
    try {
      let dir = await navigator.storage.getDirectory();
      await dir.getFileHandle('foo.txt', {create: true});
      return true;
    } catch (e) {
      return false;
    }
  }

  async function hasFileSystemAccess() {
    try {
      let dir = await navigator.storage.getDirectory();
      await dir.getFileHandle('foo.txt', { create: false });
      return true;
    } catch (e) {
      return false;
    }
  }

  async function setWebSql() {
    try {
      var db = openDatabase('testdb', '1.0', 'a test db', 1024);
      await new Promise((resolve, reject) => {
        db.transaction(function (tx) {
          tx.executeSql('CREATE TABLE IF NOT EXISTS foo (text)');
          tx.executeSql('INSERT INTO foo (text) VALUES ("bar")');
        }, reject, resolve);
      });
      return true;
    } catch (e) {
      return false;
    }
  }
  async function setWebSqlAsync() {
    // Provided for Java.
    domAutomationController.send(await setWebSql());
  }

  async function hasWebSql() {
    try {
      var db = openDatabase('testdb', '1.0', 'a test db', 1024);
      var num_results;
      await new Promise((resolve, reject) => {
        db.transaction(function (tx) {
          tx.executeSql('CREATE TABLE IF NOT EXISTS foo (text)');
          tx.executeSql('SELECT * FROM foo', [], function (tx, results) {
            num_results = results.rows.length;
          });
        }, reject, resolve);
      });
      return num_results > 0;
    } catch (e) {
      return false;
    }
  }
  async function hasWebSqlAsync() {
    // Provided for Java.
    domAutomationController.send(await hasWebSql());
  }

  function setIndexedDb() {
    var open = indexedDB.open('db', 2);
    open.onupgradeneeded = function() {
      open.result.createObjectStore('store');
    }
    return new Promise((resolve) => {
      open.onsuccess = function () {
        open.result.close();
        resolve(true);
      }
      open.onerror = () => resolve(false);
    });
  }
  async function setIndexedDbAsync() {
    domAutomationController.send(await setIndexedDb());
  }

  function hasIndexedDb() {
    var open = indexedDB.open('db');
    return new Promise((resolve) => {
      open.onsuccess = function() {
        var hasStore = open.result.objectStoreNames.contains('store');
        open.result.close();
        resolve(hasStore);
      }
      open.onerror = () => resolve(false);
    });
  }
  async function hasIndexedDbAsync() {
    domAutomationController.send(await hasIndexedDb());
  }

  function worker_(command) {
    let worker = new Worker("site_data_worker.js");
    return new Promise((resolve) => {
      worker.onmessage = e => {
        resolve(e.data);
      };
      worker.postMessage(command);
    });
  }

  function hasWorkerFileSystemAccess() {
    return worker_("hasFileSystemAccess");
  }

  function setWorkerFileSystemAccess() {
    return worker_("setFileSystemAccess");
  }

  function hasWorkerCacheStorage() {
    return worker_("hasCacheStorage");
  }

  function setWorkerCacheStorage() {
    return worker_("setCacheStorage");
  }

  function hasWorkerIndexedDb() {
    return worker_("hasIndexedDb");
  }

  function setWorkerIndexedDb() {
    return worker_("setIndexedDb");
  }

  function setHistory() {
    history.pushState({}, "foo");
    return true;
  }

  function hasHistory() {
    return history.length > 1;
  }

  let sharedWorker; // Global variable to keep worker alive.
  function connectSharedWorker() {
    return new Promise((resolve, reject) => {
      sharedWorker = new SharedWorker("shared_worker.js");
      sharedWorker.onerror = reject;
      sharedWorker.port.onmessage = resolve;
      sharedWorker.port.start();
    });
  }

  function setSharedWorker() {
    return connectSharedWorker()
    .then(() => {
      sharedWorker.port.postMessage({ "value": "foo" });
      return true;
    })
    .catch(() => false);
  }

  async function hasSharedWorker() {
    return connectSharedWorker()
    .then(() => {
      return new Promise((resolve) => {
        sharedWorker.port.onmessage = e => {
          resolve(e.data.value === "foo");
        };
        sharedWorker.port.postMessage({});
      });
    })
    .catch(() => false);
  }

  let lock;
  function setWebLock() {
    return new Promise((resolve) => {
      navigator.locks.request("foo", () => {
        lock = new Promise(() => { });
        // Now lock will be held while |lock| exists.
        resolve(true);
        return lock;
      })
    })
    .catch(() => false);
  }

  function hasWebLock() {
    return navigator.locks.query()
    .then(locks => !!locks.held.length && locks.held[0].name === "foo")
    .catch(() => false);
  }
</script>

<body>
  This page is used to test creation and deletion of various site data types.
  The functions are called from BrowsingDataRemoverBrowserTest::HasDataForType
  and BrowsingDataRemoverBrowserTest::SetDataForType.
</body>

</html>
